﻿using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Windows;
using System.Windows.Data;
using System.Windows.Media;

namespace Gmantis.Controls.Chart
{
    public class XYDataSeries : DataSeries
    {
        // Fields
        private Binding _xvaluesBinding;
        protected List<object> listX = new List<object>();
        private static DependencyProperty XValuesProperty = DependencyProperty.Register("XValues", typeof(DoubleCollection), typeof(XYDataSeries), new PropertyMetadata(null, new PropertyChangedCallback(XYDataSeries.XValuesChanged)));
        public static readonly DependencyProperty XValuesSourceProperty = Utils.RegisterProperty("XValuesSource", typeof(IEnumerable), typeof(XYDataSeries), new PropertyChangedCallback(DataSeries.OnChangeValues));

        // Methods
        internal override DataPoint CreateDataPoint(int i, int j)
        {
            return new XYDataPoint(this, i, j, this.GetDataNamesInternal());
        }

        internal override string[] GetDataNamesInternal()
        {
            return new string[] { "Values", "XValues" };
        }

        internal override ValueCoordinate[] GetValueCoordinates(bool check)
        {
            if (check)
            {
                return new ValueCoordinate[] { base.Check(ValueCoordinate.Y), base.Check(ValueCoordinate.X) };
            }
            return new ValueCoordinate[] { ValueCoordinate.Y, ValueCoordinate.X };
        }

        internal override double[,] GetValues()
        {
            if (base.datavalues == null)
            {
                if (base.ValueBinding == null)
                {
                    DataSeries.InitList(base.listY, base.ValuesSource, base.Values);
                }
                if (this.XValueBinding == null)
                {
                    DataSeries.InitList(this.listX, this.XValuesSource, this.XValues);
                }
                if (this.listX.Count == 0)
                {
                    for (int i = 0; i < base.listY.Count; i++)
                    {
                        this.listX.Add(i);
                    }
                }
                base.datavalues = base.CreateValues(new IList[] { base.listY, this.listX });
                if (base.isTimeValues == null)
                {
                    base.isTimeValues = new bool[2];
                }
                base.isTimeValues[0] = base.IsTimeData(base.listY);
                base.isTimeValues[1] = base.IsTimeData(this.listX);
                base.datavalues = base.AggregateValues(base.datavalues);
                base.datavalues = this.ProcessValues(base.datavalues);
            }
            return base.datavalues;
        }

        internal override void SetResolvedValues(int index, object[] vals)
        {
            switch (index)
            {
                case 0:
                    base.listY.Clear();
                    base.listY.AddRange(vals);
                    return;

                case 1:
                    this.listX.Clear();
                    this.listX.AddRange(vals);
                    return;
            }
        }

        private static void XValuesChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args)
        {
            ((DataSeries)obj).FirePropertyChanged("XValues");
        }

        // Properties
        public override Binding[] MemberPaths
        {
            get
            {
                if ((base.ValueBinding == null) && (this.XValueBinding == null))
                {
                    return null;
                }
                return new Binding[] { base.ValueBinding, this.XValueBinding };
            }
        }

        public Binding XValueBinding
        {
            get
            {
                return this._xvaluesBinding;
            }
            set
            {
                if (this._xvaluesBinding != value)
                {
                    this._xvaluesBinding = value;
                    base.Dirty = true;
                    base.FirePropertyChanged("XValueBinding");
                }
            }
        }

        [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
        public DoubleCollection XValues
        {
            get
            {
                return (DoubleCollection)base.GetValue(XValuesProperty);
            }
            set
            {
                base.SetValue(XValuesProperty, value);
            }
        }

        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public IEnumerable XValuesSource
        {
            get
            {
                return (IEnumerable)base.GetValue(XValuesSourceProperty);
            }
            set
            {
                base.SetValue(XValuesSourceProperty, value);
            }
        }

        // Nested Types
        [EditorBrowsable(EditorBrowsableState.Never)]
        public class XYDataPoint : DataPoint
        {
            // Methods
            internal XYDataPoint(DataSeries ds, int seriesIndex, int pointIndex, string[] names)
                : base(ds, seriesIndex, pointIndex, names)
            {
            }

            // Properties
            public object X
            {
                get
                {
                    return base.Series.GetValue(1, base.PointIndex);
                }
            }

            public string XAsString
            {
                get
                {
                    return base.Series.GetFormattedValue(1, base.PointIndex);
                }
            }

            public object Y
            {
                get
                {
                    return base.Series.GetValue(0, base.PointIndex);
                }
            }

            public string YAsString
            {
                get
                {
                    return base.Series.GetFormattedValue(0, base.PointIndex);
                }
            }
        }
    }
}
